﻿namespace FSharpChess

module Search_full =
    //fruit code
    let ExtendSingleReply = true
    let simple_stalemate psn = 
        // lone king?
        let pr = psn.PlayerToPlay
        let col = pr.prIsWhite
        let lone_king() = if col then psn.Wct<=1 else psn.Bct<=1
        // king in a corner?
        let kingid = if col then 4 else 20
        let kingsq = psn.Pcs.[kingid].SquareOrd
        let king_in_corner() = kingsq=0||kingsq=7||kingsq=56||kingsq=63
        // king can move?
        let king_cannot_move() =
            let king_sqs_to = Ref.movsK.[kingsq]
            let rec cnmoveto ordl =
                if ordl=[] then
                    true
                elif Attack.CanBeMovedToBy(ordl.Head,Attack.OtherPlayer(pr),psn,true) then
                    cnmoveto ordl.Tail
                else
                    false
            cnmoveto king_sqs_to
        lone_king()&&king_in_corner()&&king_cannot_move()
    let capture_is_dangerous mv psn =
        let pcid = mv.mvPiece
        let pc = psn.Pcs.[pcid]
        let col = pc.pcIsWhite
        let pawn_close_prom() = pc.Name=enmName.Pawn && ((col && Ref.ri.[mv.To] > 5)||((not col) && Ref.ri.[mv.To] < 2))
        let queen_cap () = if mv.pieceCaptured <> -1 && psn.Pcs.[mv.pieceCaptured].Name=enmName.Queen then true else false
        let cap_pawn_close_prom() = if mv.pieceCaptured <> -1 && psn.Pcs.[mv.pieceCaptured].Name=enmName.Pawn && ((col && Ref.ri.[mv.To] < 2)||((not col) && Ref.ri.[mv.To] > 5)) then true else false
        pawn_close_prom()||queen_cap()||cap_pawn_close_prom()
    let move_is_dangerous mv psn =
        let pcid = mv.mvPiece
        let pc = psn.Pcs.[pcid]
        let col = pc.pcIsWhite
        pc.Name=enmName.Pawn && ((col && Ref.ri.[mv.To] > 5)||((not col) && Ref.ri.[mv.To] < 2))
    let pv_fill (pv:Move List) psn =
        let rec pv_fill_det (mv:Move) mvl mpsn =
            if not (mv.isBlank()) then
                Move_do.DoMoveOK(mv,mpsn) |>ignore
                if mvl<>[] then pv_fill_det mvl.Head mvl.Tail mpsn
                Move_do.Undo(mv,mpsn)
                let move = 0us//need to encode mv to this
                let trans_move = move
                let trans_depth = -127y // HACK
                let trans_min_value = -Trans.ValueInf
                let trans_max_value = +Trans.ValueInf
                Trans.trans_store psn.Hca trans_move trans_depth trans_min_value trans_max_value
        pv_fill_det pv.Head pv.Tail psn
    let do_ver psn =
        // use verification if the side-to-move has at most one piece
        if psn.PlayerToPlay.prIsWhite then psn.Wct <= 2 else psn.Bct <= 2// king + one piece
    let do_null psn =
        // use null move if the side-to-move has at least one piece
        if psn.PlayerToPlay.prIsWhite then psn.Wct >= 2 else psn.Bct >= 2 // king + one piece
    let full_new_depth depth mv psn single_reply in_pv =
        let new_depth = depth - 1
        if ((single_reply && ExtendSingleReply)
            || (in_pv && mv.pieceCaptured <> -1 // recapture
                      && (SEE.see_move mv psn) > 0)
            || (in_pv && psn.Pcs.[mv.mvPiece].Name=enmName.Pawn
                      && (psn.PlayerToPlay.prIsWhite && Ref.ri.[mv.To] = 7 ||  not psn.PlayerToPlay.prIsWhite && Ref.ri.[mv.To] = 2)
                      && (SEE.see_move mv psn) >= 0)
            || (Move_check.move_is_check mv psn)) then
                new_depth+1 
        else new_depth
    let full_quiescence psn alpha beta depth height =
        // init
        Search.SearchCurrent.node_nb<-Search.SearchCurrent.node_nb+1UL
        Search.SearchInfo.check_nb<-Search.SearchInfo.check_nb-1;
        let pv=[]
    
    
    
        let best_value=0
        best_value,pv
        


